今天我們來更加深入 Haskell 中的 List,昨天我們講到了運用無限 List 加上一些 function 可以幫我們快速產生一個 List,但如果我們今天想要生成一個較為複雜的 List 像是產生2的平方數、1到100中的奇數呢?這時候就需要 List Comprehension
所謂的 List comprehension 就是我們可以用一些符號來描述一個 List,類似在數學上的我們想要說明一個集合是偶數的話我們會說
{ x | x=2k , k∈N }
那如果我們要在 Haskell描述一個偶數 List
[ x*2 | x <- [1..]]
可以看出來我們一樣只要說明元素的如何產生以及範圍就好,
這裡說明了每個元素都是 x*2
且 x
的範圍是從1開始的無限 List
所以用昨天的例子如果我們想要產生前17個17的倍數的話
[x*17 | x <- [1..17]]
-- [17,34,51,68,85,102,119,136,153,170,187,204,221,238,255,272,289]
當然List comprehension不只如此,假設我們今天條件更刁鑽了,例如:我想要前17個17的倍數但又不行是偶數呢?
[x*17 | x <- [1..17], x `mod` 2 /=0 ]
-- [17,51,85,119,153,187,221,255,289]
我們只要在後面加上限制條件,x
mod 2 /=0
就好了
特別說明一下
mod
的``
是把 function 變成 infix 的用法
那假設我想要把一個List 大於10的數字+1 小於10的*2 且3倍數要丟掉呢?
foo l = [if x>10 then x+1 else x*2| x <- l , x `mod` 3 /= 0]
foo [1..20]
-- [2,4,8,10,14,16,20,12,14,15,17,18,20,21]
除此之外 List comprehension 也支援多個變數跟多個條件,像是生成一個 List 它是由x
及 y
的乘積,但x
的範圍為1到5,y
的範圍為6到10,且 x+y
還不能是5的倍數
[x*y | x<-[1..5],y<-[6..10], (x+y) `mod` 5 /= 0]
還記得字串也是一種 List 嗎? 所以List Comprehension 理所當然的能夠用來生成字串或者處理字串。
像是我想要將一個 List 全部轉為小寫或者濾出這個 List 的小寫字母
[toLower x| x<- "asdqwAsdcqAsdasd" ]
[x| x<- "asdqwAsdcqAsdasd" , x `elem` ['a'..'z']]
或者濾出合法的 email
就只是簡單的驗證,當然光是這些條件不足以說明屬於email的格式
[email | email <- emailList, elem '@' email && elem '.' email ]
明天我們會開始學習有關 type 及 type class 的部分了~
今天的程式碼一樣會放到 github